#!/usr/bin/python
#
# upsw.py version 1.0
#
# Copyright (C) 2003-4 by Damien Challet <challet@maths.ox.ac.uk>
# Redistribution of this file is permitted under the terms of the GNU
# Public License (GPL), see http://www.gnu.org/copyleft/gpl.html
#

import string
import commands
import Tkinter
import sys
import math
import random



def linlogChange():
    if(linlogString.get()=="lin"):
        linlogString.set("log")
    else:
        linlogString.set("lin")

def idumChange():
    if(idumString.get()=="constant"):
       idumString.set("random")
    else:
       idumString.set("constant")



def coinFileName(swept,minval,maxval,intval):
    str=cmd+"_"+args[swept]
    if(intval==1):
        str+=`int(minval)`+"-"+`int(maxval)`
    else:
        str+=`minval`+"-"+`maxval`
    for i in range(swept):
        str+=args[i]+entryMin[i].get()

    for i in range(swept+1,len(args)):
        if(args[i]=="idum"):
            if(idumString.get()=="random"):
                str+=args[i]+"random"
            else:
                str+=args[i]+"cst"+entryMin[i].get()
        else:
            str+=args[i]+entryMin[i].get()
               
    str+="Nsamples"+`int(nrunsEntry.get())`
    str+=".dat"
    return str

    
def runcommand(swept):
    minval=float(entryMin[swept].get())
    maxval=float(entryMax[swept].get())
    Npts=int(nptsEntry.get())
    if(maxval-minval>=Npts):
        print "param takes integer values"
        intval=1
    else:
        print "param takes float values"
        intval=0

    fileName=coinFileName(swept,minval,maxval,intval)
    print "data will be written to "+fileName
    OUT=open(fileName, 'w')
    OUT.close()
       
    if(linlogString.get()=="lin"):
        log=0 
        dval=(maxval-minval)*1./Npts
    else:
        log=1
        if(minval>0):
            dval=pow((maxval*1./minval),1./Npts)
            
    val=minval
    avg=[]
    avg2=[]

    Nruns=int(nrunsEntry.get())
    stop=0
    while(val <= maxval and stop==0):
        for i in range(len(avg)):
            avg[i]=0.
            avg2[i]=0.

        for it in range(Nruns):
            str=""
            for i in range(swept):
                if(args[i]=="idum"):
                    str=str+" "+`int(random.uniform(-10000000,-1))`
                else:
                    str=str+" "+entryMin[i].get()
                    
            str+=" "+`val`

            for i in range(swept+1,len(args)):
                if(args[i]=="idum"  and idumString.get()=="random"):
                    str=str+" "+`int(random.uniform(-10000000,-1))`
                else:
                    str=str+" "+entryMin[i].get()                    
            cmdt=cmd+" "+str
#            print cmdt
            output=commands.getoutput(cmdt)
            print args[swept]+"="+`val`+" "+`it+1`+"/"+`Nruns`+" "+output
            results=string.split(output)
            if(len(avg)==0):
                for i in range(len(results)):
                    temp=float(results[i])
                    avg.append(temp)
                    avg2.append(temp*temp)
            else:
                for i in range(len(results)):
                    t=float(results[i])
                    avg[i]+=t
                    avg2[i]+=t*t
                
        toprint=`val`+" "
        for i in range(len(avg)):
            avg[i]/=Nruns
            avg2[i]/=Nruns
            avg2[i]-=avg[i]*avg[i]
            avg2[i]=math.sqrt(math.fabs(avg2[i]/Nruns))

            toprint+=" "+`avg[i]`
        for i in range(len(avg)):
            toprint+=" "+`avg2[i]`
            
        print toprint        
        OUT=open(fileName, 'a')
        OUT.write(toprint+"\n")
        OUT.close()
        oldval=val
        if(log==0):
            if(intval==1):
                if(int(val+dval)>val):
                    val=int(val+dval)
                else:
                    val=int(val+dval+1)                    
            else:
                val+=dval
            if(val>maxval and maxval-oldval>dval): #takes care of the last point that sometimes just exceeds maxval
                val=maxval
        else:
            if(intval==1):
                if(int(val*dval)>val):
                    val=int(val*dval)
                else:
                    val=int(val*dval+1)
            else:
                val*=dval
            if(val>maxval and maxval/oldval>dval*0.3 and maxval/oldval<1): #takes care of the last point that sometimes just exceeds maxval
                val=maxval

                
            
def findSweptParam():
    swept=-1
    for i in range(len(args)):
        if(entryMax[i].get()!="" and entryMin[i].get()!=""):
            if(float(entryMax[i].get())>float(entryMin[i].get())):
                if(swept<0):
                    swept=i
                else:
                    print "Error: ",swept," and ",i," have a min and a max value \007"
                    print entryMax[i], entryMin[i], entryMax[swept], entryMin[swept]
                    sys.exit()
    if(swept>=0):
        return swept
    else:
        print "Error: swept = -1  \007"
                

def run():
    if(runString.get()=="GO"):
        swept=findSweptParam()
        runcommand(swept)
#        runString.set("STOP")
        runString.set("GO")
    else:
        stop=1;
        runString.set("GO")


#program's body

LEFT, Label, Entry = Tkinter.LEFT, Tkinter.Label, Tkinter.Entry   # shortcut names

SEP=" "

cmd=sys.argv[1] #"/home/damien/minorite/corrfunc/Min"


output=commands.getoutput(cmd)

#print "command line: ",output

x=string.split(output,":")
args=string.split(x[1])

root = Tkinter.Tk()
root.title('SweepOver '+cmd+' @ '+commands.getoutput("hostname"))

args_frame = Tkinter.Frame(root)
args_frame.pack(fill=Tkinter.X, side=Tkinter.BOTTOM)

StringVar=Tkinter.StringVar

#print len(args)

Label(args_frame, text="min").grid(row=1, column=0)
Label(args_frame, text="Max").grid(row=2, column=0)

for i in range(0,len(args)):
    Label(args_frame, text=args[i],width=len(args[i])).grid(row=0, column=i+1)

entryMin=[]
entryMax=[]
for i in range(0,len(args)):
#    print i
    entryMin.append(Entry(args_frame,width=3+len(args[i])))
    entryMin[i].grid(row=1, column=i+1)

for i in range(0,len(args)):
    entryMax.append(Entry(args_frame,width=3+len(args[i])))
    entryMax[i].grid(row=2, column=i+1)

Label(args_frame, text="Npoints").grid(row=0, column=len(args)+2)
nptsEntry=Entry(args_frame,width=3+len("Npoints"))
nptsEntry.grid(row=1, column=len(args)+2)


Label(args_frame, text="#samples").grid(row=0, column=len(args)+3)
nrunsEntry=Entry(args_frame,width=3+len("#nsamples"))
nrunsEntry.grid(row=1, column=len(args)+3)



runString=StringVar()
runString.set("GO")
runButton=Tkinter.Button(args_frame, textvariable=runString, command=run)
runButton.grid(row=2, column=len(args)+4)

linlogString=StringVar()
linlogString.set("lin")
linlogButton=Tkinter.Button(args_frame, textvariable=linlogString, command=linlogChange)
linlogButton.grid(row=2, column=len(args)+2)

idumString=StringVar()
idumString.set("random")
idumButton=Tkinter.Button(args_frame,textvariable=idumString,command=idumChange)
idumButton.grid(row=2, column=len(args)+3)
      


root.mainloop()


